#include "Map.h"

Map::Map() :mpSprites(nullptr),
			mpTiles(nullptr) ,
			mColumns(0), 
			mRows(0),
			mTileSize(0)		// initializingm the first moment, better than assigning, dont put it inside the body
{
}
Map::~Map()
{
}

void Map::Load(const char* pLevel, const char* pTexturePack)
{
	Unload();

	if(!LoadLevel(pLevel))
	{
		Unload();
		return;
	}
	if(!LoadTexturePack(pTexturePack))
	{
		Unload();
		return;
	}
}

void Map::Unload()
{
	for (int i = 0; i < mNumSprites; i++)
	{
		mpSprites[i].Unload();
	}

	delete[] mpSprites;
	mpSprites = nullptr;

	delete[] mpTiles;
	mpTiles = nullptr;
	mNumSprites =0;
	mColumns =0;
	mRows =0;
	mTileSize = 0;
}

void Map::Update(float deltaTime)
{
}

void Map::Render(const SVector2& viewoffset)
{
	for (int y = 0; y < mRows; y++)
	{
		for (int x = 0; x < mColumns; x++)
		{
			const int index = GetIndex(x,y);
			SVector2 pos((float)x* mTileSize, (float)y * mTileSize);
			SVector2 renderPosition = pos - viewoffset;
			mpSprites[mpTiles[index]].SetPosition(renderPosition);
			mpSprites[mpTiles[index]].Render();
		}
	}
}

bool Map::TestCollision(const SLineSegment& segment, SRect& rect) const
{
	if(segment.from.x < 0.0f  || segment.from.x >= GetWidth() || segment.from.y < 0.0f || segment.from.y >= GetHeight()||
		segment.to.x < 0.0f  || segment.to.x >= GetWidth() || segment.to.y < 0.0f || segment.to.y >= GetHeight())
	{
		return false;
	}
	int minX =(int)(segment.from.x / mTileSize);
	int minY =(int)(segment.from.y / mTileSize);
	int maxX =(int)(segment.to.x / mTileSize);
	int maxY =(int)(segment.to.y / mTileSize);

	rect = SRect();

	bool collision = false;
	for(int y =minY; y<= maxY; y++)
	{
		for (int x = minX; x <= maxX; x++)
		{
			if(IsBlocked(x,y))
			{
				rect += GetBoundingBox(x,y);
				collision = true;
			}
			/*const int index = GetIndex(x,y);
			mpTiles[index]*/
		}
	}
	return collision;
}

bool Map::LoadLevel(const char* pLevel)
{
		FILE* pFile= nullptr;
	fopen_s(&pFile, pLevel, "r");
	if(pFile == nullptr)
	{
		return false;
	}

	fscanf_s(pFile, "%*s %d", &mTileSize);
	fscanf_s(pFile, "%*s %d", &mColumns);
	fscanf_s(pFile, "%*s %d", &mRows);

	mpTiles = new int[mColumns * mRows];

	fgetc(pFile);								// character 0 in ascii is 48
	for (int y = 0; y < mRows; y++)
	{
		for (int x = 0; x < mColumns; x++)
		{
			const int index = GetIndex(x,y);
			mpTiles[index] = fgetc(pFile) -'0';
		}
		fgetc(pFile);
	}
	fclose(pFile);
	return true;
}
bool Map::LoadTexturePack(const char* pTexturePack)
{
	FILE* pFile= nullptr;
	fopen_s(&pFile, pTexturePack, "r");
	if(pFile == nullptr)
	{
		return false;
	}

	fscanf_s(pFile, "%*s %d", &mNumSprites);
	

	mpSprites = new SGE_Sprite[mNumSprites];

	char buffer[256];
	for (int i = 0; i < mNumSprites; i++)
	{
		fscanf_s(pFile, "%s", buffer, 256);
		mpSprites[i].Load(buffer);
	}														// character 0 in ascii is 48
	fclose(pFile);
	return true;
}

int Map::GetIndex(int x, int y) const
{
	return x + (y * mColumns);
}

bool Map::IsBlocked(int x, int y) const
{
	const int index = GetIndex(x,y);
	int type = mpTiles[index];
	return (type > 1);	//	This is a HACK: Assumes  >1 not walkable
	/*if(type >1)
	{
		return true;
	}
	else
	{
		return false;
	}*/
}

SRect Map::GetBoundingBox(int x, int y) const
{
	SRect boundingBox;
	boundingBox.min.x =(float) x * mTileSize ;
	boundingBox.min.y =(float) y * mTileSize;
	boundingBox.max.x =(float) ((x+1) * mTileSize);
	boundingBox.max.y =(float) ((y+1) * mTileSize);
	return boundingBox;
}
// remind to talk about ***, also about delete [] , delte